package com.zklh.book.system;

import com.zklh.book.system.common.model.RestResponse;
import com.zklh.book.system.enums.UserRoleEnum;
import com.zklh.book.system.model.Book;
import com.zklh.book.system.model.User;
import com.zklh.book.system.rest.BookController;
import com.zklh.book.system.rest.UserController;
import com.zklh.book.system.service.UserService;
import com.zklh.book.system.service.impl.UserServiceImpl;
import com.zklh.book.system.util.BeanFactory;
import com.zklh.book.system.view.Operationtwo;
import com.zklh.book.system.view.ViewRenderer;
import com.zklh.book.system.view.render.*;
import com.zklh.book.system.view.OperationOption;
import com.zklh.book.system.service.UserService;

import java.util.*;

/**
 * 启动入口类
 * 这里就会组装各个组件进行 使用
 * @author 坐看落花
 * @version 1.0
 * @date 2021/3/20 19:23
 */
public class Starter {

    // 定义静态的目的是为了让其他的方法, 不仅仅是main方法 也可以使用这些系统对外提供的接口
    private static UserController userController = BeanFactory.getBean(UserController.class);
    private static BookController bookController = BeanFactory.getBean(BookController.class);
    private static Scanner sc = new Scanner(System.in);
//    private static UserService userService;
//    private UserService userService = BeanFactory.getBean(UserServiceImpl.class);

    public static void  main(String[] args) throws InterruptedException {
        // 系统组件, 这些组件是直接对外的, 而service 和 repo等都是内部的, 不能对外暴露, 可能不安全或者有其他情况
        ViewRenderer homeViewRender = new HomeViewRenderer();
        ViewRenderer operationViewRenderer = new OperationViewRenderer();
        ViewRenderer bookTableViewRenderer = new BookTableViewRenderer();
        ViewRenderer mybookTableViewRenderer = new MyBookTableViewRenderer();
        ViewRenderer onebookTableViewRenderer = new OneBookTableViewRenderer();
        ViewRenderer caseoperation = new CaseoperationViewRenderer();

        // 记录当前登录人的用户信息
        User user = produceLogin();

        List<OperationOption> operations = getOperations();
        List<Operationtwo> operationcase = getOperationstwo();

        /* 登录成功后, 渲染首页, params 是首页需要的参数, 这里需要看代码才知道params要传哪些参数 */
        Map<String,Object> params = new HashMap<>();
        params.put("username",user.getName());
        params.put("role", user.getRole());
        params.put("operations", operations);
        // 首次进入系统, 渲染主页,
        homeViewRender.render(params);
        // 渲染可执行指令列表
        operationViewRenderer.render(params);


        // 这里就是一个死循环 一直监听用户输入, 直到用户输入退出系统指令, 这里用了很多的if, else 判断用户输入的指令是什么, 以及应该调用哪个controller的方法, 更好的方式应该是查表
        // 举个例子, 用一个map存储 指令对应的方法是什么, 然后 直接通过 map.get(actionCode) 的方式获取方法, 然后反射调用方法, 但是这样做可能比较难理解, 这里使用简单的方式实现
        while (true) {
            System.out.print("请输入指令:");
            String actionCode = sc.nextLine().trim();;

            /* 判断输入指令是否是系统允许范围内的指令 */
            int action = 0;
            // 判断是否输入指令是数字
            try {
                action = Integer.parseInt(actionCode);
            } catch (NumberFormatException e) {
                System.out.println("输入指令错误, 请重新输入");
                continue;
            }
            // 判断输入指令是不是包含在指令集合中
            boolean allowExecute = false;
            for (OperationOption operation : operations) {
                if (operation.getCode() == action) {
                    allowExecute = true;
                }
            }
            // token 存在的意义就是用户的登录标识, 当你调用接口的时候, 系统需要知道是谁在调用接口
            String token = user.getToken();
            /* 这里根据输入的指令, 做请求的分发, 这里是把代码比较长的部分 抽出去, 代码短的留下, 代码短在这里可读性还是很高的 */
            if(allowExecute) {
                switch (action){
                    case 1: // 查看书列表
                        RestResponse<List<Book>> response1 = bookController.list(token);
                        if (response1.getSuccess()) {
                            Map<String,Object> params1 = new HashMap<>();
                            params1.put("books", response1.getData());//没看到getData具体实现函数?//ctrl+鼠标定位到接口声明,ctrl+alt+鼠标左键 接口实现类
                            bookTableViewRenderer.render(params1);//ctrl+alt+左键
                        } else {
                            System.err.println("--------");
                            System.err.println("查询书列表失败," + response1.getMsg());
                            System.err.println("--------");
                        }
                        break;
                    case 2: // 借书
                        System.out.print("请输入书编号:");
                        String bookCode = sc.nextLine().trim();
                        RestResponse<String> response2 = bookController.borrow(token, bookCode);
                        if (response2.getSuccess()) {
                            System.out.println("--------");
                            System.out.println("借书成功");
                            System.out.println("--------");
                        } else {
                            System.err.println("--------");
                            System.err.println("借书失败," + response2.getMsg());
                            System.err.println("--------");
                        }
                        break;
                    case 3: // 还书
                        System.out.print("请输入书编号:");
                        String backCode = sc.nextLine().trim();;
                        RestResponse<String> response3 = bookController.back(token, backCode);
                        if (response3.getSuccess()) {
                            System.out.println("--------");
                            System.out.println("还书成功");
                            System.out.println("--------");
                        } else {
                            System.err.println("--------");
                            System.err.println("还书失败," + response3.getMsg());
                            System.err.println("--------");
                        }
                        break;
                    case 4: // 新增书
                        // 调用保存书接口
                        produceSaveBook(token);
                        operationViewRenderer.render(params);
                        break;
                    case 5: // 上架书
                        System.out.print("请输入书编号:");
                        String bookCode5 = sc.nextLine().trim();
                        RestResponse<String> response = bookController.enable(token, bookCode5);
                        if (response.getSuccess()) {
                            System.out.println("--------");
                            System.out.println("上架成功");
                            System.out.println("--------");
                        } else {
                            System.err.println("--------");
                            System.err.println("上架失败,"+response.getMsg());
                            System.err.println("--------");
                        }
                        break;
                    case 6: // 下架书
                        System.out.print("请输入书编号:");
                        String bookCode6 = sc.nextLine().trim();;
                        RestResponse<String> response6 = bookController.disable(token, bookCode6);
                        if (response6.getSuccess()) {
                            System.out.println("--------");
                            System.out.println("下架成功!");
                            System.out.println("--------");;
                        } else {
                            System.err.println("--------");
                            System.err.println(response6.getMsg());
                            System.err.println("--------");
                        }
                        break;
                    case 7: // 删除书
                        System.out.print("请输入书编号:");
                        String bookCode7 = sc.nextLine().trim();;
                        RestResponse<String> response7 = bookController.delete(token, bookCode7);
                        if (response7.getSuccess()) {
                            System.out.println("--------");
                            System.out.println("删除成功!");
                            System.out.println("--------");
                        } else {
                            System.err.println("--------");
                            System.err.println(response7.getMsg());
                            System.err.println("--------");
                        }
                        break;
                    case 8: // 退出系统
                        userController.logout(token);
                        System.out.println("正在退出登录...");
                        System.out.println("3秒后关闭系统...");
                        Thread.sleep(1000);
                        System.out.println("2秒后关闭系统...");
                        Thread.sleep(1000);
                        System.out.println("1秒后关闭系统...");
                        Thread.sleep(1000);
                        System.exit(0);
                        break;
                    //tongting tianjia
                    case 9://查看我的借书列表
                        RestResponse<List<Book>> response9 = bookController.mylist(token);
                        if (response9.getSuccess()) {
                            Map<String,Object> params1 = new HashMap<>();
                            params1.put("books", response9.getData());
                            mybookTableViewRenderer.render(params1);
                        } else{
                            System.err.println("--------");
                            System.err.println("查询书列表失败," + response9.getMsg());
                            System.err.println("--------");
                        }

                        break;

                    case 10://修改图书信息与一些选项重复,应该增加的内容为改变书的编号,书名,总数,数量,状态,且这些内容只能管理员权限可以更改
//                        User users = userService.getByToken(token);
//                        if (!UserRoleEnum.ADMIN.getKey().equals(users.getRole())) {
//                            System.out.println("权限不足!");
//                        }
                        System.out.print("请输入书编号:");
                        String bookCode10 = sc.nextLine().trim();
                        //获取一本书的内容并渲染页面
                        RestResponse<Book> response10 = bookController.onelist(token,bookCode10);
                        if (response10.getSuccess()) {
                            Map<String, Object> params2 = new HashMap<>();
                            params2.put("book",response10.getData());
                            onebookTableViewRenderer.render(params2);
                        }else{
                            System.err.println("--------");
                            System.err.println("查询本书失败," + response10.getMsg());
                            System.err.println("--------");
                        }
                        //打印可以更改的图书信息
                        System.out.println("以下是可以更改的图书信息内容");
                        Map<String,Object> params10 = new HashMap<>();
                        params10.put("operationcase", operationcase);
                        caseoperation.render(params10);
                        System.out.println("\t");
                        System.out.println("输入你选择的指令");
                        String actioncase = sc.nextLine().trim();;
                        /* 判断输入指令是否是系统允许范围内的指令 */
                        int actionnow = 0;
                        // 判断是否输入指令是数字
                        try {
                            actionnow = Integer.parseInt(actioncase);
                        } catch (NumberFormatException e) {
                            System.out.println("输入指令错误, 请重新输入");
                            continue;
                        }
                        // 判断输入指令是不是包含在指令集合中
                        boolean allow = false;
                        for (Operationtwo operation10 : operationcase) {
                            if (operation10.getCode() == action) {
                                allow = true;
                            }
                        }
                        switch(actionnow){
                            //修改书编号后,原书编号还是可以使用
                            case 1:
                                System.out.print("请输入修改后的书编号:");
                                String code= sc.nextLine().trim();
                                RestResponse<String> response10_1 = bookController.changenumber(bookCode10, code);
                                if (response10_1.getSuccess()) {
                                    System.out.println("--------");
                                    System.out.println("修改成功!");
                                    System.out.println("--------");
                                } else {
                                    System.err.println("--------");
                                    System.err.println(response10_1.getMsg());
                                    System.err.println("--------");
                                }
                                break;
                            case 2:
                                System.out.print("请输入修改后的书名:");
                                String name= sc.nextLine().trim();
                                RestResponse<String> response10_2 = bookController.changecode(token,bookCode10, name);
                                if (response10_2.getSuccess()) {
                                    System.out.println("--------");
                                    System.out.println("修改成功!");
                                    System.out.println("--------");
                                } else {
                                    System.err.println("--------");
                                    System.err.println(response10_2.getMsg());
                                    System.err.println("--------");
                                }
                                break;
                            case 3:
                                System.out.println("目前不知道case3与case4的关系");
                                break;
                            case 4:
                                System.out.print("请输入修改后的数目:");
                                String sum_n = sc.nextLine().trim();
                                Integer sum= Integer.parseInt(sum_n);
                                RestResponse<String> response10_3 = bookController.changeremain(bookCode10,sum);
                                if (response10_3.getSuccess()) {
                                    System.out.println("--------");
                                    System.out.println("修改成功!");
                                    System.out.println("--------");
                                } else {
                                    System.err.println("--------");
                                    System.err.println(response10_3.getMsg());
                                    System.err.println("--------");
                                }
                                break;
                            case 5:
                                System.out.println("case5,case6,case7已经实现了这个功能!");
                                break;

                        }
                        break;

                    case 0: // 登出系统, 重新登录
                        userController.logout(token);
                        System.out.println("--------");
                        System.out.println("退出成功===");
                        System.out.println("--------");
                        user = produceLogin();
                        params.put("role", user.getRole());
                        params.put("username", user.getName());
                        homeViewRender.render(params);
                        break;
                    default:
                        System.err.println("--------");
                        System.err.println("功能尚未开放, 敬请期待!");
                        System.err.println("--------");
                        break;
                }
            } else {
                System.out.println("--------");
                System.err.println("输入错误, 指令不在系统预设范围内");
                System.out.println("--------");
            }
            // 上个指令执行结束后, 再次打印指令列表, 不打印首页了
            operationViewRenderer.render(params);

        }


    }

    private static void produceSaveBook(String token) {
        // 用于控制是否继续输入参数
        boolean goOn = true;
        // 用于存储是否正常获得录入参数
        boolean getBookParam = false;
        String[] infos = null;
        while(goOn) {
            goOn = false;
            System.out.print("请录入书的信息(格式: 编号,书名,数量 ; 注:英文','分隔):");
            String bookStr = sc.nextLine().trim();;
            infos = bookStr.split(",");
            boolean hasError = false;
            String msg = "";
            if (infos.length < 3) {
                hasError = true;
                msg = "参数数量不足";
            } else if (infos.length >= 3) {
                try {
                    int tempInt = Integer.parseInt(infos[2]);
                    if (tempInt < 0) {
                        hasError = true;
                        msg = "数量不能为负数";
                    }
                } catch (NumberFormatException e) {
                    hasError = true;
                    msg = "数量参数不是数字";
                }
            }

            if (hasError) {
                getBookParam = false;
                System.err.println("录入格式错误, "+msg+","+"是否尝试重新录入(Y/N):");
                String goOnStr = sc.nextLine().trim();;
                if ("Y".equals(goOnStr)) {
                    goOn = true;
                } else{
                    goOn = false;
                }
            } else {
                getBookParam = true;
            }
        }
        if (getBookParam) {
            Book book = new Book();
            book.setCode(infos[0]);
            book.setName(infos[1]);
            book.setAmount(Integer.parseInt(infos[2]));
            RestResponse<String> response = bookController.add(token, book);
            if (response.getSuccess()) {
                System.out.println("--------");
                System.out.println("保存成功!");
                System.out.println("--------");
            } else {
                System.err.println("--------");
                System.err.println("保存失败!"+response.getMsg());
                System.err.println("--------");
            }
        }
    }

    private static User produceLogin() {
        boolean loginSuccess = false;
        User user = null;
        while (!loginSuccess) {
            System.out.print("account:");
            String account = sc.nextLine().trim();
            System.out.print("password:");
            String password = sc.nextLine().trim();;
            RestResponse<User> restResponse = userController.login(account, password);
            if (restResponse.getSuccess()) {
                user = restResponse.getData();
                loginSuccess = true;
            } else {
                System.out.println("密码错误!请重新输入");
            }
        }
        return user;
    }


    /**
     * 把operations 拉出来是为了方便管理
     * @return
     */
    private static List<OperationOption> getOperations(){
        return Arrays.asList(
                new OperationOption(1, "查看书列表", Arrays.asList(UserRoleEnum.CONSUMER.getKey(), UserRoleEnum.ADMIN.getKey())),
                new OperationOption(2, "借书", Arrays.asList(UserRoleEnum.CONSUMER.getKey())),
                new OperationOption(3, "还书", Arrays.asList(UserRoleEnum.CONSUMER.getKey())),
                new OperationOption(4, "新增书", Arrays.asList(UserRoleEnum.ADMIN.getKey())),
                new OperationOption(5, "上架书", Arrays.asList(UserRoleEnum.ADMIN.getKey())),
                new OperationOption(6, "下架书", Arrays.asList(UserRoleEnum.ADMIN.getKey())),
                new OperationOption(7, "删除", Arrays.asList(UserRoleEnum.ADMIN.getKey())),
                new OperationOption(8, "退出系统", Arrays.asList(UserRoleEnum.CONSUMER.getKey(), UserRoleEnum.ADMIN.getKey())),
                new OperationOption(9, "查看我的借书列表", Arrays.asList(UserRoleEnum.CONSUMER.getKey())),
                new OperationOption(10, "修改图书信息", Arrays.asList( UserRoleEnum.ADMIN.getKey())),
                new OperationOption(11, "查看个人信息(待开发)", Arrays.asList( UserRoleEnum.UNKNONW.getKey())),
                new OperationOption(12, "修改个人信息(待开发)", Arrays.asList( UserRoleEnum.UNKNONW.getKey())),
                new OperationOption(13, "修改密码(待开发)", Arrays.asList( UserRoleEnum.UNKNONW.getKey())),
                new OperationOption(14, "查看所有用户(待开发)", Arrays.asList( UserRoleEnum.UNKNONW.getKey())),
                new OperationOption(0, "注销", Arrays.asList( UserRoleEnum.ADMIN.getKey(), UserRoleEnum.CONSUMER.getKey()))
        );
    }

    private static List<Operationtwo> getOperationstwo(){
        return Arrays.asList(
                new Operationtwo(1,"更换书编号"),
                new Operationtwo(2,"更改书名"),
                new Operationtwo(3,"更改书的总数"),
                new Operationtwo(4, "更改书的剩余数量"),
                new Operationtwo(5, "更改书的状态")
        );
    }

}
